﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using Library.Models;
using Library.Utils;
using log4net;

namespace Library.Repository
{
    public class UserRepository : IUserRepository
    {
        private static readonly ILog Log = LogManager.GetLogger("UserRepository");
        private readonly UserList _users;
        private readonly String _xmlPath;

        public UserRepository()
        {
            Log.Info("constructor");

            if (IsLinux) _xmlPath = @"/home/pi/InteligentnyDom/SerialisationToFileTest/bin/Debug/users.xml";
            else
                _xmlPath = @"D:\raspberryPI\Projects\trunk\InteligentnyDom\SerialisationToFileTest\bin\Debug\users.xml";
            var serializer = new XmlSerializer(typeof (UserList));

            TextReader rstream = new StreamReader(_xmlPath);

            _users = (UserList) serializer.Deserialize(rstream);
            rstream.Close();

            Log.Info("constructor_end");
        }

        public static bool IsLinux
        {
            get
            {
                var p = (int) Environment.OSVersion.Platform;
                return (p == 4) || (p == 6) || (p == 128);
            }
        }

        #region IUserRepository Members

        public User GetOrDie(string login)
        {
            Log.Info("GetOrDie: " + login);

            try
            {
                return _users.List.Single(u => u.Login == login);
            }
            catch (Exception)
            {
                string list = _users.List.Aggregate("", (current, user) => current + (user.Login + " "));

                throw new UserNotFoundException("Użytkownik " + login + " nie istnieje. Dostępni: " + list);
            }
        }

        public User Add(User user)
        {
            Log.Info("Add: " + user.Name);

            if (_users.List.Count(u => u.Login == user.Login) != 0)
                throw new UserAlreadyExistsException("Użytkownik " + user.Login + " już istnieje w systemie");

            _users.List.Add(user);
            Persist();

            Log.Info("Add_end");
            return user;
        }

        public User ChangeRole(string login, UserRole role)
        {
            Log.Info("ChangeRole: " + login + " " + role);

            User user = GetOrDie(login);
            user.Role = (int) role;
            Persist();

            Log.Info("ChangeRole_end");
            return user;
        }

        public User ChangePassword(string login, string password)
        {
            Log.Info("ChangePassword: " + login);

            User user = GetOrDie(login);
            user.Pass = password;
            Persist();


            Log.Info("ChangePassword_end");
            return user;
        }

        public User ChangeName(string login, string name)
        {
            Log.Info("ChangeName: " + login + " " + name);

            User user = GetOrDie(login);
            user.Name = name;
            Persist();

            Log.Info("ChangeName_end");
            return user;
        }

        public void RemoveUser(string login)
        {
            Log.Info("RemoveUser: " + login);

            User user = GetOrDie(login);
            _users.List.Remove(user);
            Persist();

            Log.Info("RemoveUser_end");
        }

        #endregion

        public List<User> GetAll()
        {
            Log.Info("GetAll");

            return _users.List;
        }


        private void Persist()
        {
            Log.Info("Persist");

            var serializer = new XmlSerializer(typeof (UserList));
            TextWriter wstream = new StreamWriter(_xmlPath);
            serializer.Serialize(wstream, _users);
            wstream.Close();
            
            Log.Info("Persist_end");
        }


        public static void GenerateTestUsers()
        {
            var users = new UserList();
            ;
            var serializer = new XmlSerializer(typeof (UserList));
            TextWriter wstream =
                new StreamWriter(
                    @"D:\raspberryPI\projects\trunk\MvcApplication3\SerialisationToFileTest\bin\Debug\users.xml");
            users = new UserList();
            users.List.Add(new User
                               {Login = "Admin", Name = "Administrator..", Pass = "123qwe", Role = (int) UserRole.Admin});
            users.List.Add(new User {Login = "User", Name = "User..", Pass = "123qwe", Role = (int) UserRole.User});
            users.List.Add(new User {Login = "Viewer", Name = "Viewer..", Pass = "123qwe", Role = (int) UserRole.Viewer});

            serializer.Serialize(wstream, users);
            wstream.Close();
        }
    }


    public interface IUserRepository
    {
        User GetOrDie(string login);

        User Add(User user);

        User ChangeRole(string login, UserRole role);

        User ChangePassword(string login, string password);

        User ChangeName(string login, string name);

        void RemoveUser(string login);
    }
}